Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Allow dots in XJS identifiers <com.tag /> #6

Closed
wants to merge 1 commit into from
Closed

Allow dots in XJS identifiers <com.tag /> #6

wants to merge 1 commit into from

Conversation

syranide
Copy link

I feel like this would be a natural fit for React, for those who may prefer not to use CommonJS-style imports. It simply adds the ability to use dots in tags like <com.xjs.tag /> and translates straight to JS.

A side-effect of this is that it also allows dots in attribute names (both are XJS-identifiers), which may or may not be useful. However, hyphens are currently allowed (for attributes I assume), they however produce an error when used in XJS-tags (JS interprets it as subtraction).

I'm personally not in need of this, it's simply a suggestion.

@jeffmo
Copy link

jeffmo commented Dec 21, 2013

We've talked this through before and ultimately decided that dots where not the right solution (but the general idea isn't off the table): facebook/react#221

The tldr is: It doesn't make sense for JSX's definition of what an 'identifier' is to deviate from JS's definition. Rather, if we were to go down this road, we should formalize namespacing into the syntax tree.

We came to the conclusion that, if we we're going to have something like this, we should use proper xml namespacing syntax (a la :). This would allow for a sugared namespacing syntax that can then be interpreted by the compiler however necessary.

For example, some may wish for namespace separators to be interpreted in terms of member expressions (i.e. compile down to dots), whereas others may not want to have to rely on nesting namespaced components in sub-objects and may instead want something like (for example) underscore_namespacing. If we went this route and supported sugar-namespaced components, we'd then just pick a sane default for the JSX compiler and add a parameter to override it for anyone who cares to.

In any case, if you want to proceed with this idea feel free -- we'll just want to implement it generically in the parser.

(See facebook/react#221 (comment) where I outlined an example node structure)

@jeffmo
Copy link

jeffmo commented Dec 21, 2013

It just occurred to me that if we allow parameterization of the syntax semantics, this would pose inter-op issues with any components that someone may want to share publicly (open-source, etc). So while I still think the syntax tree should be properly abstracted, maybe adding a parameter to the compiler isn't a good idea after all and we should just decide on one or the other (dots or underscores or "ಠ_ಠ"s -- too bad "⚛" isn't valid).

@syranide
Copy link
Author

@jeffmo I'm not understanding your second reply a 100%, anyway, this was just an off-shoot thing when testing/tugging on React/JSX, I'm not currently seeing any use of this for myself, it just looked like a simple fix when I spotted it.

If it is something you are interested in then it seems like it should be easy enough to fix generically (technically), but it's not exactly burning a hole in my pants. :)

@jeffmo
Copy link

jeffmo commented Dec 21, 2013

Right on -- yea dots-in-identifiers is something we're not actively interested in; So unless you are, I don't know if this is worth pursuing

@syranide syranide closed this Dec 22, 2013
@syranide syranide deleted the xjsidentdot branch December 24, 2013 22:58
@rcs
Copy link

rcs commented Dec 27, 2013

I just ran into this and @syranide was nice enough to point me here.

The use case is something like "MyFancyComponentLibrary".

var fancyLib = require('fancy-lib');

React.createClass({
  mixins: [fancyLib.mixins.superAwesome],
  render: function() {
    return (
      <fancyLib.pickers.datePicker />
      <fancyLib.pickers.clockPicker />
      <fancyLib.copyrightLine />
    );
  }
});

Without dot-namespacing, any use of a component out of fancy-lib requires something looking more like:

var fancyLib = require('fancy-lib');

React.createClass({
  mixins: [fancyLib.mixins.superAwesome],
  render: function() {
    var datePicker = fancyLib.pickers.datePicker;
    var clockPicker = fancyLib.pickers.clockPicker;
    var copyright = fancyLib.copyrightLine;
    return (
      <datePicker />
      <clockPicker />
      <copyrightLine />
    );
  }
});

Which makes libraries written for other people to use harder and introduces more boilerplate.

@syranide
Copy link
Author

@jeffmo I saw another person asking the same thing earlier, and it seems like it could be useful for saw ReactART/etc as well. I could look into doing the proper "namespaced" version (and extend JSX accordingly). Is that ok or would you prefer to hold off on this?

@jeffmo
Copy link

jeffmo commented Dec 27, 2013

Implementing proper namespacing in the parser + corresponding syntax tree structure would be a good first step and shouldn't be too hard.

After that well just need to get a discussion going on the semantics of that syntax: Does namespacing mean MemberExpression (i.e. Foo.Bar)? Or delimited identifier (i.e.`Foo_Bar)? They both have merits and pros/cons, so we should consider them carefully

@jeffmo
Copy link

jeffmo commented Dec 27, 2013

In @rcs's example, clearly MemberExpression would be ideal.

One of the reasons we've rejected namespaces at Facebook (internally) is because we've found it to be an anti-pattern to nest a bunch of submodules within one large parent module. Instead we find it best to isolate components into their own smaller modules that you can require and compose as-needed. This bodes much better for making it easy to minimize the amount of code that needs to be shipped to the client. It also helps re-inforce the decoupling of components into smaller pieces (which is important as they age and are contributed by many other devs).

On the other hand, you could imagine a use-case like this:

var LibAButton = require('lib-a/button');
var LibBButton = require('lib-b/button');

<div><LibAButton /><LibBButton /></div>

If we added a namespace separator in this case all we'd be doing is baking a convention for how you can specify your namespaced components. MemberExpressions push that convention into the module code for the namespaced component (ie modules must export {LibA: {Button: Button}}). Delimiter-namespacing pushes the convention into the local code where you import it (ie locally you must do var LibA_Button = require('lib-a/button'); if you wish to use the <LibA:Button /> syntax). The former is a pretty tricky convention to convey except by convention (Oh, LibraryA uses namespaces...but LibraryB doesnt -- so I need to be aware of this when importing components from the two libs). The latter is just syntax sugar that's isolated to the implementation of your module. Anyone can use it if they want, but you don't have to.

@syranide
Copy link
Author

@jeffmo From my perspective, it would simply return a feature that JS has today, that JSX currently lacks. In JS you can do ReactART.Gradient(null). In JSX you can't, you have to var ReactART_Gradient = require('react-art').Gradient and then you can do <ReactART_Gradient /> for every component.

So in my mind <ReactART.Gradient /> would translate to ReactART.Gradient(null), and possibly given some weird names <ReactART.1stObject /> would translate to ReactART['1stObject'].

@zpao
Copy link

zpao commented Jan 2, 2014

Did we decide for sure on the colon for namespacing? I thought we were pretty evenly divided between wanting that and the period. If we want JSX to really be a real XML dialect, then the colon makes sense. But with the period, we can very easily stick to our story of being a very simple bit of sugar on JS. "not in React.DOM? then we assume a function".

@syranide
Copy link
Author

syranide commented Jan 2, 2014

@zpao I haven't read the discussions in-depth, just glancing it seemed like at least @jeffmo was in favor of colon.

Personally, I really can't say I care, using colon would make it look like XML, but we've already deviated from that syntax for attributes and expressions so I don't see any greater purpose to it (can't use XML highlighters anyway). Using dot would be familiar and represent a more obvious intuition of the translation, and possibly greater freedom in extending JSX in the future, but to me it kind of seems like this is last extensions that can be easily argued for. With this (and possibly what I mention below), JSX would be equal to JS in flexibility, pure sugar.

While we're on the subject, I would like to propose being able to send an object to props as we can in regular JS, it is very useful. Depending on your preferences, it could be as simple as <div props={myObject} /> and specifying any other property would yield an error (or React will have to export a merge utility function, which is an issue since the docblock identifies React.DOM and not React).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants